<!-- Copyright (C) 2019-2021 Junruoyu Zheng. Home page: https://junruoyu-zheng.gitee.io/ligral

     Distributed under MIT license.
     See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
-->
<!DOCTYPE html>
<html lang="en">
 <head>
  <title>
   路由类型
  </title>
  <meta charset="utf-8"/>
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport"/>
  <!-- Main CSS -->
  <link href="/ligral/css/style.css" rel="stylesheet"/>
  <link href="/ligral/css/rolling.css" rel="stylesheet"/>
  <link href="/ligral/css/custom.css" rel="stylesheet"/>
  <link href="/ligral/css/katex.min.css" rel="stylesheet"/>
  <link href="/ligral/avatar.png" rel="shortcut icon" type="image/x-icon"/>
  <!-- Font Awesome -->
  <script crossorigin="anonymous" src="https://kit.fontawesome.com/14294c79e2.js">
  </script>
 </head>
 <body>
  <!-- Header -->
  <div class="header-wrap d-none d-md-block">
   <div class="container">
    <div class="row">
     <!-- Left header box -->
     <header class="col-6 text-left">
      <h1 class="letter-wrap title">
       Ligral
      </h1>
     </header>
    </div>
   </div>
  </div>
  <!-- Main navigation -->
  <nav class="navbar navbar-expand-md navbar-dark bg-primary">
   <div class="container">
    <!-- Company name shown on mobile -->
    <a class="navbar-brand d-md-none d-lg-none d-xl-none" href="#">
     Ligral
    </a>
    <!-- Mobile menu toggle -->
    <button aria-controls="mainNavbar" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#mainNavbar" data-toggle="collapse" type="button">
     <span class="navbar-toggler-icon">
     </span>
    </button>
    <!-- Main navigation items -->
    <div class="collapse navbar-collapse" id="mainNavbar">
     <ul class="navbar-nav mr-auto">
      <li class="nav-item">
       <a class="nav-link" href="/ligral/index.html">
        主页
        <span class="sr-only">
         (current)
        </span>
       </a>
      </li>
      <li class="nav-item dropdown active">
       <a aria-expanded="false" aria-haspopup="true" class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button">
        文档
       </a>
       <div class="dropdown-menu navbar-dark bg-primary">
        <a class="dropdown-item" href="/ligral/quick-start.html">
         快速开始
        </a>
        <a class="dropdown-item" href="/ligral/user-guide">
         用户文档
        </a>
        <a class="dropdown-item" href="/ligral/dev-guide">
         开发文档
        </a>
        <a class="dropdown-item" href="/ligral/interface/">
         接口定义
        </a>
       </div>
      </li>
      <!-- <li class="nav-item">
                                <a class="nav-link" href="#">Services</a>
                        </li> -->
      <li class="nav-item">
       <a class="nav-link" href="/ligral/product.html">
        产品
       </a>
      </li>
      <li class="nav-item">
       <a class="nav-link" href="/ligral/contact.html">
        联系我们
       </a>
      </li>
     </ul>
     <!-- <form class="form-inline header-search-form my-2 my-lg-0">
                        <input class="form-control mr-sm-2" type="text" size="10"  placeholder="Search" aria-label="Search">
                        <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
                    </form> -->
    </div>
   </div>
  </nav>
  <!-- Jumbtron / Slider -->
  <!-- Main content area -->
  <main class="container">
   <div class="row" style="flex-direction: row-reverse;">
    <!-- Main content -->
    <div class="col-sm-8">
     <article>
      <h1>
       路由类型
      </h1>
      <p>
       Ligral 是一个面向对象的仿真语言，您可以在 ligral 中创建路由类型，然后进行若干次实例化从而得到多个实例。我们相信这在仿真场景中是非常实用的。例如您设计了一个弹簧类，在进行某个机构仿真的时候，您可能需要引入多个弹簧模型，此时您可以声明多个弹簧实例，而不是把代码复制一遍。
      </p>
      <h3>
       路由与类/方法的异同
      </h3>
      <p>
       路由这一概念和 c++ 中的类有些相似，但又有所不同。相同之处在于：
      </p>
      <ul>
       <li>
        它们都规定了一类承载数据、包含功能的物体；
       </li>
       <li>
        都允许从类型本身克隆出实例；
       </li>
       <li>
        都能根据参数的不同而在具体功能实现上保留差异。
       </li>
      </ul>
      <p>
       不同之处在于：
      </p>
      <ul>
       <li>
        路由所包含的功能逻辑是比较单一的，即根据输入计算输出，不存在成员方法；
       </li>
       <li>
        路由仅有输入输出端口是公共的，其他成员是内部私有的，不允许修改成员的访问属性。
       </li>
      </ul>
      <p>
       从类的角度来说，路由实例的声明就相当于调用构造函数，下面代码对比了 ligral 语法的实例声明语法（详见
       <a href="node">
        节点声明
       </a>
       ）和 c++ 风格的实例声明语法：
      </p>
      <pre><code># ligral
Spring[spring]{K:10};
// c++
auto spring = new Spring(10);
</code></pre>
      <p>
       可以看到两条语句承载的信息是一样的（ligral 仅支持显式指定参数名的方式定义参数，而 c++ 默认使用位置参数，因此 ligral 语句多了一个
       <code>
        K
       </code>
       ）。在之后的代码中，均可以通过
       <code>
        spring
       </code>
       标识符来引用这个实例。Ligral 的实例声明语句之所以如此设计，是方便您在调用时声明，且仍能将实例绑定到标识符上，这在 c++ 中是无法做到的。
      </p>
      <pre><code># ligral
Step[src] -&gt; Model;
src -&gt; Print;
// c++
auto src = new Step();
src.to(new Model());
src.to(new Print());
</code></pre>
      <p>
       从类克隆出实例后，路由看起来更像是一个方法。事实上，路由的作用很多时候就是实现了一个方法（函数），根据输入计算输出。不考虑求解器循环调用，下面两个语句的作用效果是等效的：
      </p>
      <pre><code># ligral
x -&gt; Sin -&gt; y;
// c++
y = sin(x);
</code></pre>
      <p>
       如果您只熟悉数学公式，那么 c++ 的写法显然更直观；如果您已经习惯于使用 Simulink，ligral 的语法也很简单明了。Ligral 之所以这么设计，是方便您级联调用而不产生任何后果；反观 c++ 的语法，会让程序末尾多了很多括号，影响可读性。Ligral 的调用方式和 shell 脚本中 pipe 调用有些类似，不过 shell 语法采用了一种混合式的风格。
      </p>
      <pre><code># ligral
x -&gt; Sin -&gt; Abs -&gt; y;
// c++
y = abs(sin(x));
# shell
y=$(echo $x | sin | abs)
</code></pre>
      <p>
       从这个角度看，路由像是一种元方法，即创建方法的方法，通过一些参数的选择，生成略有不同的方法，这和 python 的装饰器有点像。
      </p>
      <h2>
       路由的定义
      </h2>
      <p>
       路由的定义语句从
       <code>
        route
       </code>
       关键字开始，到
       <code>
        end
       </code>
       关键字结束，其中包含头部的属性信息以及主体部分的逻辑信息。
      </p>
      <h3>
       路由的属性
      </h3>
      <p>
       通常路由定义语句的第一行包含了路由的属性，包括路由的名称、签名、参数、输入输出端口，其中父类、参数和输入输出都是可省的，语法如下：
      </p>
      <pre><code>route RouteName(;;) ...
route RouteName:Interface(;;) ...
route RouteName(parameters; inputs; outputs) ...
</code></pre>
      <p>
       第一行显示了省略所有可省部分的语法。第二行展示了如何声明一个路由声明签名，关于签名的具体使用请查看
       <a href="signature">
        接口签名
       </a>
       小节，此处仅介绍语法。
      </p>
      <p>
       第三行说明了参数和输入的顺序，它们都在一对圆括号里，被两个分号分别分开。即使其中任何一个被省略了，分号也不能省略。输入和输出的语法十分简单，就是用逗号分隔端口名，端口的书写顺序就是编号顺序。
      </p>
      <p>
       参数的语法稍微复杂一些。首先，参数从可省性上分为可省参数和不可省参数，可省参数需要指定参数名和默认参数值，不可省参数只要指定参数名；其次，从参数类型又可分为常量参数和节点参数，顾名思义，常量参数接受一个常量，节点参数接受声明特定签名的节点。节点参数必须指定签名，常量参数无需指定。
      </p>
      <pre><code># 常量不可省参数
param1,
# 常量可省参数
param2 = 0,
# 节点不可省参数
param3:NodeSignature, ...
</code></pre>
      <p>
       节点参数只能是不可省参数，因为参数的默认值在路由类型（而不是其实例）被创建的时候就被创建了，因此全局仅有一份拷贝。如果您为这个路由声明了两个实例，两个实例的这个参数均绑定到同一个节点上，必然会造成
       <code>
        Duplicated binding of InPort.
       </code>
       错误。
      </p>
      <h3>
       路由的主体
      </h3>
      <p>
       路由的主体部分语法和整个 ligral 程序一致。在路由内部，您可以使用常量声明语句定义局部变量，除此之外，路由的所有参数都是局部变量。更重要的是您可以声明节点，描述节点之间的连接方式，确保除了输入以外所有的节点都是被连接的，所有输入节点都是未连接的。
      </p>
      <p>
       此外，目前设置语句和导入语句也是可以在路由内部使用的，不过未来很可能会禁用设置语句，因为没有实际应用场景，而且会让人产生困扰。
      </p>
      <h3>
       一个完整的例子
      </h3>
      <p>
       本节暂不讨论和接口签名有关的内容。以一个 PID 控制器为例，展示如何定义一个路由（
       <code>
        TransferFunction
       </code>
       模块尚未实现）：
      </p>
      <pre><code>route PIDController(Kp, Ki=0, Kd=0, tau=0.01; x; u)
    x -&gt; Integrator[xi];
    x -&gt; TransferFunction[xdot]{num=[1, 0], den=[tau, 1]};
    x * Kp + xi * Ki + xdot * Kd -&gt; u;
end
</code></pre>
      <p>
       这个路由的名字为
       <code>
        PIDController
       </code>
       ，有四个参数，除了
       <code>
        Kp
       </code>
       之外其他的为可选参数。前三个是控制器增益，如果您忽略了
       <code>
        Ki
       </code>
       参数，那么您实际上声明了一个 PD 控制器的实例，忽略了
       <code>
        Kd
       </code>
       则得到 PI 控制器。第四个参数是微分所需的一个时间常数。输入和输出各只有一个，输出由输入本身、输入的积分和微分乘上对应的增益相加而得到，写成传递函数的形式就是：
      </p>
      <p>
       <span class="katex-display">
        <span class="katex">
         <span class="katex-mathml">
          <math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
           <semantics>
            <mrow>
             <mi>
              u
             </mi>
             <mo stretchy="false">
              (
             </mo>
             <mi>
              s
             </mi>
             <mo stretchy="false">
              )
             </mo>
             <mo>
              =
             </mo>
             <msub>
              <mi>
               K
              </mi>
              <mi>
               p
              </mi>
             </msub>
             <mi>
              x
             </mi>
             <mo stretchy="false">
              (
             </mo>
             <mi>
              s
             </mi>
             <mo stretchy="false">
              )
             </mo>
             <mo>
              +
             </mo>
             <msub>
              <mi>
               K
              </mi>
              <mi>
               i
              </mi>
             </msub>
             <mi>
              x
             </mi>
             <mo stretchy="false">
              (
             </mo>
             <mi>
              s
             </mi>
             <mo stretchy="false">
              )
             </mo>
             <mfrac>
              <mn>
               1
              </mn>
              <mi>
               s
              </mi>
             </mfrac>
             <mo>
              +
             </mo>
             <msub>
              <mi>
               K
              </mi>
              <mi>
               d
              </mi>
             </msub>
             <mi>
              x
             </mi>
             <mo stretchy="false">
              (
             </mo>
             <mi>
              s
             </mi>
             <mo stretchy="false">
              )
             </mo>
             <mfrac>
              <mi>
               s
              </mi>
              <mrow>
               <mi>
                τ
               </mi>
               <mi>
                s
               </mi>
               <mo>
                +
               </mo>
               <mn>
                1
               </mn>
              </mrow>
             </mfrac>
            </mrow>
            <annotation encoding="application/x-tex">
             u(s) = K_px(s)+K_ix(s)\frac{1}{s}+K_dx(s)\frac{s}{\tau s+1}
            </annotation>
           </semantics>
          </math>
         </span>
         <span aria-hidden="true" class="katex-html">
          <span class="base">
           <span class="strut" style="height:1em;vertical-align:-0.25em;">
           </span>
           <span class="mord mathnormal">
            u
           </span>
           <span class="mopen">
            (
           </span>
           <span class="mord mathnormal">
            s
           </span>
           <span class="mclose">
            )
           </span>
           <span class="mspace" style="margin-right:0.2777777777777778em;">
           </span>
           <span class="mrel">
            =
           </span>
           <span class="mspace" style="margin-right:0.2777777777777778em;">
           </span>
          </span>
          <span class="base">
           <span class="strut" style="height:1.036108em;vertical-align:-0.286108em;">
           </span>
           <span class="mord">
            <span class="mord mathnormal" style="margin-right:0.07153em;">
             K
            </span>
            <span class="msupsub">
             <span class="vlist-t vlist-t2">
              <span class="vlist-r">
               <span class="vlist" style="height:0.15139200000000003em;">
                <span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;">
                 <span class="pstrut" style="height:2.7em;">
                 </span>
                 <span class="sizing reset-size6 size3 mtight">
                  <span class="mord mathnormal mtight">
                   p
                  </span>
                 </span>
                </span>
               </span>
               <span class="vlist-s">
                ​
               </span>
              </span>
              <span class="vlist-r">
               <span class="vlist" style="height:0.286108em;">
                <span>
                </span>
               </span>
              </span>
             </span>
            </span>
           </span>
           <span class="mord mathnormal">
            x
           </span>
           <span class="mopen">
            (
           </span>
           <span class="mord mathnormal">
            s
           </span>
           <span class="mclose">
            )
           </span>
           <span class="mspace" style="margin-right:0.2222222222222222em;">
           </span>
           <span class="mbin">
            +
           </span>
           <span class="mspace" style="margin-right:0.2222222222222222em;">
           </span>
          </span>
          <span class="base">
           <span class="strut" style="height:2.00744em;vertical-align:-0.686em;">
           </span>
           <span class="mord">
            <span class="mord mathnormal" style="margin-right:0.07153em;">
             K
            </span>
            <span class="msupsub">
             <span class="vlist-t vlist-t2">
              <span class="vlist-r">
               <span class="vlist" style="height:0.31166399999999994em;">
                <span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;">
                 <span class="pstrut" style="height:2.7em;">
                 </span>
                 <span class="sizing reset-size6 size3 mtight">
                  <span class="mord mathnormal mtight">
                   i
                  </span>
                 </span>
                </span>
               </span>
               <span class="vlist-s">
                ​
               </span>
              </span>
              <span class="vlist-r">
               <span class="vlist" style="height:0.15em;">
                <span>
                </span>
               </span>
              </span>
             </span>
            </span>
           </span>
           <span class="mord mathnormal">
            x
           </span>
           <span class="mopen">
            (
           </span>
           <span class="mord mathnormal">
            s
           </span>
           <span class="mclose">
            )
           </span>
           <span class="mord">
            <span class="mopen nulldelimiter">
            </span>
            <span class="mfrac">
             <span class="vlist-t vlist-t2">
              <span class="vlist-r">
               <span class="vlist" style="height:1.32144em;">
                <span style="top:-2.314em;">
                 <span class="pstrut" style="height:3em;">
                 </span>
                 <span class="mord">
                  <span class="mord mathnormal">
                   s
                  </span>
                 </span>
                </span>
                <span style="top:-3.23em;">
                 <span class="pstrut" style="height:3em;">
                 </span>
                 <span class="frac-line" style="border-bottom-width:0.04em;">
                 </span>
                </span>
                <span style="top:-3.677em;">
                 <span class="pstrut" style="height:3em;">
                 </span>
                 <span class="mord">
                  <span class="mord">
                   1
                  </span>
                 </span>
                </span>
               </span>
               <span class="vlist-s">
                ​
               </span>
              </span>
              <span class="vlist-r">
               <span class="vlist" style="height:0.686em;">
                <span>
                </span>
               </span>
              </span>
             </span>
            </span>
            <span class="mclose nulldelimiter">
            </span>
           </span>
           <span class="mspace" style="margin-right:0.2222222222222222em;">
           </span>
           <span class="mbin">
            +
           </span>
           <span class="mspace" style="margin-right:0.2222222222222222em;">
           </span>
          </span>
          <span class="base">
           <span class="strut" style="height:1.8768900000000002em;vertical-align:-0.7693300000000001em;">
           </span>
           <span class="mord">
            <span class="mord mathnormal" style="margin-right:0.07153em;">
             K
            </span>
            <span class="msupsub">
             <span class="vlist-t vlist-t2">
              <span class="vlist-r">
               <span class="vlist" style="height:0.33610799999999996em;">
                <span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;">
                 <span class="pstrut" style="height:2.7em;">
                 </span>
                 <span class="sizing reset-size6 size3 mtight">
                  <span class="mord mathnormal mtight">
                   d
                  </span>
                 </span>
                </span>
               </span>
               <span class="vlist-s">
                ​
               </span>
              </span>
              <span class="vlist-r">
               <span class="vlist" style="height:0.15em;">
                <span>
                </span>
               </span>
              </span>
             </span>
            </span>
           </span>
           <span class="mord mathnormal">
            x
           </span>
           <span class="mopen">
            (
           </span>
           <span class="mord mathnormal">
            s
           </span>
           <span class="mclose">
            )
           </span>
           <span class="mord">
            <span class="mopen nulldelimiter">
            </span>
            <span class="mfrac">
             <span class="vlist-t vlist-t2">
              <span class="vlist-r">
               <span class="vlist" style="height:1.10756em;">
                <span style="top:-2.314em;">
                 <span class="pstrut" style="height:3em;">
                 </span>
                 <span class="mord">
                  <span class="mord mathnormal" style="margin-right:0.1132em;">
                   τ
                  </span>
                  <span class="mord mathnormal">
                   s
                  </span>
                  <span class="mspace" style="margin-right:0.2222222222222222em;">
                  </span>
                  <span class="mbin">
                   +
                  </span>
                  <span class="mspace" style="margin-right:0.2222222222222222em;">
                  </span>
                  <span class="mord">
                   1
                  </span>
                 </span>
                </span>
                <span style="top:-3.23em;">
                 <span class="pstrut" style="height:3em;">
                 </span>
                 <span class="frac-line" style="border-bottom-width:0.04em;">
                 </span>
                </span>
                <span style="top:-3.677em;">
                 <span class="pstrut" style="height:3em;">
                 </span>
                 <span class="mord">
                  <span class="mord mathnormal">
                   s
                  </span>
                 </span>
                </span>
               </span>
               <span class="vlist-s">
                ​
               </span>
              </span>
              <span class="vlist-r">
               <span class="vlist" style="height:0.7693300000000001em;">
                <span>
                </span>
               </span>
              </span>
             </span>
            </span>
            <span class="mclose nulldelimiter">
            </span>
           </span>
          </span>
         </span>
        </span>
       </span>
      </p>
     </article>
    </div>
    <!-- Sidebar -->
    <aside class="col-sm-4">
     <div class="sidebar-box">
      <h4>
       目录
      </h4>
      <div class="list-group list-group-root">
       <a class="list-group-item" href="/ligral/quick-start.html">
        快速开始
       </a>
       <a class="list-group-item" href="/ligral/user-guide/index.html">
        用户文档
       </a>
       <div class="list-group">
        <a class="list-group-item" href="/ligral/user-guide/terms.html">
         术语定义
        </a>
        <a class="list-group-item" href="/ligral/user-guide/config.html">
         设置语句
        </a>
        <a class="list-group-item" href="/ligral/user-guide/const.html">
         声明常量
        </a>
        <a class="list-group-item" href="/ligral/user-guide/node.html">
         声明节点
        </a>
        <a class="list-group-item" href="/ligral/user-guide/link.html">
         节点连接
        </a>
        <a class="list-group-item" href="/ligral/user-guide/matrix.html">
         矩阵运算
        </a>
        <a class="list-group-item active" href="/ligral/user-guide/route.html">
         路由类型
        </a>
        <a class="list-group-item" href="/ligral/user-guide/signature.html">
         接口签名
        </a>
        <a class="list-group-item" href="/ligral/user-guide/import.html">
         引用依赖
        </a>
       </div>
       <a class="list-group-item" href="/ligral/dev-guide/index.html">
        开发文档
       </a>
       <div class="list-group">
        <a class="list-group-item" href="/ligral/dev-guide/syntax.html">
         语法设计
        </a>
        <a class="list-group-item" href="/ligral/dev-guide/interpreter.html">
         解释器
        </a>
        <a class="list-group-item" href="/ligral/dev-guide/component.html">
         模块组件
        </a>
        <a class="list-group-item" href="/ligral/dev-guide/simulation.html">
         问题抽象
        </a>
        <a class="list-group-item" href="/ligral/dev-guide/tools.html">
         工具箱
        </a>
       </div>
       <a class="list-group-item" href="/ligral/interface/index.html">
        接口定义
       </a>
       <div class="list-group">
        <a class="list-group-item" href="/ligral/interface/model.html">
         模块接口
        </a>
        <a class="list-group-item" href="/ligral/interface/protocol.html">
         数据接口
        </a>
       </div>
      </div>
     </div>
     <div class="sidebar-box sidebar-box-bg">
      <h4>
       关于我们
      </h4>
      <p>
       我们是一群有志于突破工业软件封锁、具有开源精神的开发者。本项目旨在替代 Simulink 进行仿真，通过与框图等效的文本语言描述仿真对象，并解释/编译而后求解。
       <a class="readmore" href="https://gitee.com/junruoyu-zheng/ligral/wikis" target="_blank">
        更多 »
       </a>
      </p>
     </div>
     <div class="sidebar-box">
      <h4>
       仓库链接
      </h4>
      <ul>
       <li>
        <a href="https://gitee.com/junruoyu-zheng/ligral" target="_blank" title="Gitee">
         Gitee 仓库
        </a>
       </li>
       <li>
        <a href="https://github.com/JRY-Zheng/ligral" target="_blank" title="GitHub">
         GitHub 仓库
        </a>
       </li>
      </ul>
     </div>
    </aside>
   </div>
  </main>
  <!-- Footer -->
  <footer class="footer">
   <div class="footer-lists">
    <div class="container">
     <div class="row">
      <div class="col-sm">
       <ul>
        <li>
         <h4>
          联系我们
         </h4>
        </li>
        <li>
         <a href="mailto:zhengjry@outlook.com">
          给我们发邮件
         </a>
        </li>
        <li>
         <a href="https://www.zhihu.com/people/LostFish" target="_blank">
          来知乎关注我
         </a>
        </li>
        <li>
         <a href="https://web.okjike.com/u/105ad022-f646-48c0-8236-6007ee5179c5" target="_blank">
          来即刻关注我
         </a>
        </li>
       </ul>
      </div>
      <div class="col-sm">
       <ul>
        <li>
         <h4>
          代码仓库
         </h4>
        </li>
        <li>
         <a href="https://gitee.com/junruoyu-zheng/ligral" target="_blank">
          Gitee 仓库
         </a>
        </li>
        <li>
         <a href="https://github.com/JRY-Zheng/ligral" target="_blank">
          GitHub 仓库
         </a>
        </li>
       </ul>
      </div>
      <div class="col-sm">
       <ul>
        <li>
         <h4>
          合作伙伴
         </h4>
        </li>
        <li>
         <a href="http://pyminer.com" target="_blank">
          PyMiner 官网
         </a>
        </li>
        <li>
         <a href="https://gitee.com/py2cn/pyminer" target="_blank">
          PyMiner 仓库地址
         </a>
        </li>
       </ul>
      </div>
      <div class="col-sm">
       <h4>
        致谢
       </h4>
       <p>
        Ligral 的开发得到了很多帮助，特在此致谢！感谢我的单位对创新的鼓励；感谢我的导师 James 对数值积分的指导；感谢 Gitee 对项目的支持，在刚开源不久就为我推荐；感谢 PyMiner 开发团队对我的鼓励和支持！
       </p>
       <p class="social-icons">
        <a href="https://gitee.com/junruoyu-zheng/ligral/stargazers" style="text-decoration: none;" target="_blank">
         <img alt="star" src="https://gitee.com/junruoyu-zheng/ligral/badge/star.svg?theme=dark"/>
        </a>
        <a href="https://www.zhihu.com/people/LostFish" target="_blank">
         <i class="fab fa-zhihu fa-2x zhihu-icon">
         </i>
        </a>
       </p>
      </div>
     </div>
    </div>
   </div>
   <div class="footer-bottom">
    <p class="text-center">
     Copyright © 2021. Ligral All rights reserved. 梨果科技版权所有 © 2021
    </p>
    <p class="text-center">
     <a href="#">
      <i class="fa fa-arrow-up">
      </i>
      回到顶部
     </a>
    </p>
   </div>
  </footer>
  <!-- Bootcamp JavaScript -->
  <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  <script src="/ligral/js/jquery-3.2.1.slim.min.js">
  </script>
  <script src="/ligral/js/popper.min.js">
  </script>
  <script src="/ligral/js/bootstrap.min.js">
  </script>
  <script src="/ligral/js/TweenMax.min.js">
  </script>
  <script src="/ligral/js/rolling.js">
  </script>
 </body>
</html>